home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
SGI Hot Mix 17
/
Hot Mix 17.iso
/
HM17_SGI
/
research
/
lib
/
voronoi.pro
< prev
next >
Wrap
Text File
|
1997-07-08
|
8KB
|
247 lines
; $Id: voronoi.pro,v 1.7 1997/01/15 03:11:50 ali Exp $
;
; Copyright (c) 1992-1997, Research Systems, Inc. All rights reserved.
; Unauthorized reproduction prohibited.
function isright, x0, y0, x1, y1, x2, y2
; return 1 if Pnt0 is to right of Pnt1-> Pnt2
; return 0 if it is on the line.
; return -1 if Pnt0 is to the left of Pnt1 -> Pnt2
z = (x0-x1) * (y2-y1) - (y0-y1) * (x2-x1)
if z gt 0.0 then return, 1
if z lt 0.0 then return, -1
return, 0
end
PRO voronoi_get_intersect, rect, x0, y0, dx, dy, xi, yi, nedge
; Return the closest intersection of the line thru (x0, y0), with
; slope (dx / dy), and the rectangle rect. The intersection must
; be in the "positive" direction.
; Set (xi, yi) to the intersection point, and
; nedge to the edge index. Edge 0 is the bottom, going CCW.
;
nedge = -1
tmin = 0.
if dy ne 0.0 then begin
t = (rect[1] - y0) / dy ;Bottom = edge 0?
if t ge 0.0 then begin
tmin = t
nedge = 0
yi = rect[1] ;Intersection with bottom
xi = x0 + t * dx
endif
t = (rect[3] - y0) / dy ;Top edge = 2
if t ge 0.0 then $
if (nedge lt 0) or (t lt tmin) then begin
tmin = t
nedge = 2
yi = rect[3]
xi = x0 + t * dx
endif
endif ;dy ne 0
if dx ne 0.0 then begin ;Check sides?
t = (rect[0] - x0) / dx ;Left edge = 3
if t ge 0.0 then $
if (nedge lt 0) or (t lt tmin) then begin
tmin = t
nedge = 3
xi = rect[0]
yi = y0 + t * dy
endif
t = (rect[2] - x0) / dx ;Right edge = 1
if t ge 0.0 then $
if (nedge lt 0) or (t lt tmin) then begin
tmin = t
nedge = 1
xi = rect[2]
yi = y0 + t * dy
endif
endif ;Dx ne 0
end
pro VORONOI_SHOW, n ;Illustrate using and drawing Voronoi polygons
; This procedure generates N random points (default = 12).
; and then draws the voronoi polygons, with the points and
; delaunay triangulation overlaid.
if n_elements(n) le 0 then n = 12 ;Make the random points
seed = 1211567L
x = randomu(seed, n)
y = randomu(seed, n)
triangulate, x, y, tr, CONN=c ;Triangulate them
plot,x,y,/psym, xrange=[-.5,1.5], yrange=[-.5,1.5]
tek_color ;Discrete color tables.
range = 0 ;Init bounding rectangle
for i=0, n-1 do begin ;Each VORONOI region for each point
voronoi, x, y, i, c, xp, yp, range ;Get the ith polygon
xp = xp > (-10) < 10 ;Clip to reasonable space
yp = yp > (-10) < 10
polyfill, xp, yp, color = (i mod 13) + 2 ;Show it
endfor
oplot,x,y,/psym, color=1 ;Show points & triangulation
for i=0, n_elements(tr)/3-1 do begin ;The triangles
t = [tr(*,i),tr(0,i)] ;Subscripts of triangle & back to 0
plots,x(t), y(t)
endfor
end
PRO voronoi, x, y, i0, c, xp, yp, rect
; Copyright (c) 1992, Research Systems, Inc. All rights reserved.
; Unauthorized reproduction prohibited.
;+
; NAME:
; VORONOI
;
; PURPOSE:
; This procedure computes the Voronoi polygon of a point within
; an irregular grid of points, given the Delaunay triangulation.
; The Voronoi polygon of a point contains the region closer to
; that point than to any other point.
;
; CATEGORY:
; Gridding.
;
; CALLING SEQUENCE:
; VORONOI, X, Y, I0, C, Xp, Yp, Rect
;
; INPUTS:
; X: An array containing the X locations of the points.
; Y: An array containing the Y locations of the points.
; I0: Index of the point of which to obtain the Voronoi polygon.
; C: A connectivity list from the Delaunay triangulation.
; This list is produced with the CONNECTIVITY keyword
; of the TRIANGULATE procedure.
; Rect the bounding rectangle: [Xmin, Ymin, Xmax, Ymax].
; Because the Voronoi polygon (VP) for points on the convex hull
; extends to infinity, a clipping rectangle must be supplied to
; close the polygon. This rectangle has no effect on the VP of
; interior points. If this rectangle does not enclose all the
; Voronoi vertices, the results will be incorrect. If this
; parameter, which must be a named variable, is undefined or
; set to a scalar value, it will be calculated.
;
; OUTPUTS:
; Xp, Yp: The vertices of voroni polygon, VP.
;
; RESTRICTIONS:
; The polygons only cover the convex hull of the set of points.
;
; PROCEDURE:
; For interior points, the polygon is constructed by connecting
; the midpoints of the lines connecting the point with its Delaunay
; neighbors. Polygons are traversed in a counterclockwise direction.
;
; For exterior points, the set described by the midpoints of the
; connecting lines, plus the circumcenters of the two triangles
; that connect the point to the two adjacent exterior points.
;
; EXAMPLE:
; See the example procedure, VORONOI_SHOW, contained in this file.
; To illustrate Voronoi polygons, after compiling this file (voronoi):
; VORONOI_SHOW, Npoints (try anywhere from 3 to 1000, default=12)
;
; To draw the voroni polygons of each point of an irregular
; grid:
; x = randomu(seed, n) ;Random grid of N points
; y = randomu(seed, n)
; triangulate, x, y, tr, CONN=c ;Triangulate it
; rect = 0
; for i=0, n-1 do begin
; voronoi, x, y, i, c, xp, yp, rect ;Get the ith polygon
; polyfill, xp, yp, color = (i mod 10) + 2 ;Draw it
; endfor
;
; MODIFICATION HISTORY:
; DMS, RSI. Dec, 1992. Original version.
; DMS, RSI Feb, 1995. Added bounding rectangle which simplified
; logic and better illustrated VPs for points
; on the convex hull.
;-
COMMON VORONOI_COMMON, first ;Only print warning once.
if n_params() lt 7 and n_elements(first) le 0 and !quiet eq 0 then begin
Message, /INFO, 'New revision. For more efficient use, supply the Rect parameter'
first = 1
endif
p = c(c(i0):c(i0+1)-1) ;Verts of polygon
np = n_elements(p)
xp = fltarr(np, /NOZERO)
yp = fltarr(np, /NOZERO)
ext = i0 eq p(0) ;True if exterior point
; Each vertex is simply the circumcenter of a Delaunay triangle
; containing the point in question.
for i=0, np-1 do begin ;Traverse adjacency list for point i0.
m = p(i)
j = p((i + 1) mod np) ;Successor
cir_3pnt, x([m,j,i0]), y([m,j,i0]), r, x0, y0
xp[i] = x0
yp[i] = y0
endfor
if ext eq 0 then return ;If interior point, we're all done....
; *** Point is on the Convex Hull ****
if n_elements(rect) ne 4 then begin ;Initialize bounding rect?
i1 = i0 ;Follow boundary CCW
xmin = min(x, max=xmax)
ymin = min(y, max=ymax)
xr = (xmax-xmin)*.05 ;Fudge factor of 5%
yr = (ymax-ymin)*.05
rect = [xmin-xr, ymin-yr, xmax+xr, ymax+yr] ;Initial bound box
repeat begin ;Get circumctr of each boundary triangle
k = c(i1)
m = c(k+1)
j = c(k+2)
cir_3pnt, x([m,j,i1]), y([m,j,i1]), r, x0, y0
rect[0] = rect[0] < x0
rect[2] = rect[2] > x0
rect[1] = rect[1] < y0
rect[3] = rect[3] > y0 ;Keep extremes
i1 = m ;Next boundary point
endrep until i1 eq i0
endif
; Now get intersections of perpendicular bisectors of the two edges
; on the convex hull, with vertex point i0, with the bounding rectangle.
;
j = p(1)
voronoi_get_intersect, rect, xp[1], yp[1], y[j]-y[i0], x[i0]-x[j], x0, y0,edge0
xp[0] = x0
yp[0] = y0
j = p(np - 1)
voronoi_get_intersect, rect, xp[np-2], yp[np-2], y[i0]-y[j], x[j]-x[i0], $
x0, y0, edge1
xp[np-1] = x0
yp[np-1] = y0
if (edge0 < edge1) lt 0 then begin ;Either out of bounds?
MESSAGE, /INFO, 'Bounding rectangle does not enclose Voronoi polygon'
xp[0] = xp[1] ;Fudge polygon, its wrong anyway...
yp[0] = yp[1]
xp[np-1] = xp[np-2]
yp[np-1] = yp[np-2]
return
endif
while edge1 ne edge0 do begin ;Add corner(s) of bound rect if necess.
edge1 = (edge1 + 1) mod 4 ;Go CCW
xp = [xp, rect[([0,2,2,0])[edge1]]]
yp = [yp, rect[([1,1,3,3])[edge1]]]
endwhile
return
end